package sampleguiplugin;

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.HashSet;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.text.AbstractDocument.Content;

import gamefw.framework.Coordinate;
import gamefw.framework.Move;
import gamefw.gameplugin.ISpecialEventListener;
import gamefw.uiplugin.IInputManager;

public class SampleGUIInputManager implements IInputManager, ActionListener, MouseListener, WindowListener {
	
	private JFrame mainFrame;
	
	private Set<ISpecialEventListener> specialEventListeners;
	
	// Click
	private boolean waitingForClick;
	
	private Coordinate lastClickPosition;
	
	// Drag
	private boolean waitingForDrag;
	
	private Coordinate lastDragFrom;
	
	private Coordinate lastDragTo;
	
	public SampleGUIInputManager(JFrame mainFrame) {
		this.mainFrame = mainFrame;
		
		this.waitingForClick = false;
		this.waitingForDrag = false;
		
		this.lastClickPosition = null;
		this.lastDragFrom = null;
		this.lastDragTo = null;
		
		this.mainFrame.addWindowListener(this);
		
		this.specialEventListeners = new HashSet<ISpecialEventListener>();
	}

	@Override

	public synchronized void getStartSignal() {
		try {
			Container content = mainFrame.getContentPane();
			
			JButton button = new JButton("Start Game");
			button.setActionCommand("startGame");
			button.addActionListener(this);
			
			content.add(button);
			
			wait();
			
			button.setVisible(false);
			content.remove(button);
			
			button = new JButton("Quit");
			button.setActionCommand("quitGame");
			button.addActionListener(this);
			content.add(button);

			this.mainFrame.setVisible(true);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public boolean getPlayerRole(int playerIndex) {
		while (true) {
			String[] options = new String[] { "Human", "Computer" };
			
			String playerRole = (String) JOptionPane.showInputDialog(this.mainFrame,
					"Who will play Player" + playerIndex + "?",
					"Choose Player Role",
					JOptionPane.QUESTION_MESSAGE,
					null,
					options,
					options[0]);
			
			if (playerRole == null) { 
				continue;
			}
			
			return playerRole.equals("Human");
		}
	}

	@Override
	public synchronized Coordinate getPosition() {
		this.waitingForClick = true;
		try {
			this.mainFrame.getContentPane().addMouseListener(this);
			
			wait();

			this.mainFrame.getContentPane().removeMouseListener(this);

			Coordinate result = this.lastClickPosition;
			this.lastClickPosition = null;
			
			return result;
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}

	@Override
	public synchronized Move getMove() {
		this.waitingForDrag = true;
		try {
			this.mainFrame.getContentPane().addMouseListener(this);
			
			wait();

			this.mainFrame.getContentPane().removeMouseListener(this);
			
			Move result = new Move(this.lastDragFrom, this.lastDragTo);
			this.lastDragFrom = null;
			this.lastDragTo = null;
			
			return result;
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}

	@Override
	public void registerSpecialEventListener(ISpecialEventListener listener) {
		this.specialEventListeners.add(listener);
	}

	@Override
	public synchronized void actionPerformed(ActionEvent arg0) {
		if (arg0.getActionCommand().equals("startGame")) {
			notify();
		} else if (arg0.getActionCommand().equals("quitGame")) {
			for (ISpecialEventListener listener : this.specialEventListeners) {
				listener.onQuit();
			}
		}
	}

	@Override
	public synchronized void mouseClicked(MouseEvent arg0) {
		if (this.waitingForClick) {
			
			this.lastClickPosition = new Coordinate(arg0.getX(), arg0.getY());
			
			this.waitingForClick = false;
			notify();
		}
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public synchronized void mousePressed(MouseEvent arg0) {
		if (this.waitingForDrag) {
			this.lastDragFrom = new Coordinate(arg0.getX(), arg0.getY());
		}
	}

	@Override
	public synchronized void mouseReleased(MouseEvent arg0) {
		if (this.waitingForDrag && this.lastDragFrom != null) {
			
			this.lastDragTo = new Coordinate(arg0.getX(), arg0.getY());
			
			this.waitingForDrag = false;
			notify();
			
		} else {
			this.lastDragFrom = null;
			this.lastDragTo = null;
		}
	}

	@Override
	public void windowActivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosed(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosing(WindowEvent arg0) {
		for (ISpecialEventListener listener : this.specialEventListeners) {
			listener.onQuit();
		}
	}

	@Override
	public void windowDeactivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeiconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowIconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowOpened(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

}
